#include <tsin/display/DecoratedImage.hpp>
#include <tsin/display/Image.hpp>
#include <tsin/library/BuiltinImages.hpp>

using namespace tsin;

DecoratedImage::DecoratedImage(Image &image)
        : image(image), reverse(false), handler(0)
{
        xLeft = yBottom = 0.0f;
        xRight = yTop = 1.0f;
        _r = _g = _b = _a = 1.0f;
        _blendStyle = COVERING;
        _nrFrames = 1;
        _curFrame = 0;

        image.ref();
}

DecoratedImage::~DecoratedImage()
{
        image.unref();
}

void DecoratedImage::init(ImageInfo *info)
{
        setXRange(info->x, info->x + info->w);
        setYRange(info->y, info->y + info->h);
        setBlendStyle(info->blendStyle);
        setNrFrames(info->nrFrames);
        setHandler(info->handler);
}

unsigned int DecoratedImage::getHandle()
{
        return image.getHandle();
}

StandardResolution DecoratedImage::getResolution()
{
        return image.getResolution();
}

void DecoratedImage::setXRange(int left, int right)
{
        xLeft = static_cast<float>(left) / image.getWidth();
        xRight = static_cast<float>(right) / image.getWidth();
}

void DecoratedImage::setXRange(float left, float right)
{
        xLeft = left;
        xRight = right;
}

void DecoratedImage::setYRange(int bottom, int top)
{
        yBottom = static_cast<float>(bottom) / image.getHeight();
        yTop = static_cast<float>(top) / image.getHeight();
}

void DecoratedImage::setYRange(float bottom, float top)
{
        yBottom = bottom;
        yTop = top;
}

float DecoratedImage::left()
{
        return xLeft;
}

float DecoratedImage::right()
{
        return xRight;
}

float DecoratedImage::bottom()
{
        return yBottom;
}

float DecoratedImage::top()
{
        return yTop;
}

float DecoratedImage::width()
{
        return xRight - xLeft;
}

float DecoratedImage::height()
{
        return yTop - yBottom;
}

void DecoratedImage::setRGBA(float r, float g, float b, float a)
{
        if (r >= 0.0f && r <= 1.0f)
                this->_r = r;
        if (g >= 0.0f && g <= 1.0f)
                this->_g = g;
        if (b >= 0.0f && b <= 1.0f)
                this->_b = b;
        if (a >= 0.0f && a <= 1.0f)
                this->_a = a;
}

void DecoratedImage::setBlendStyle(BlendStyle style)
{
        if (style != BLEND_DEFAULT)
                _blendStyle = style;
}

float DecoratedImage::r()
{
        return _r;
}

float DecoratedImage::g()
{
        return _g;
}

float DecoratedImage::b()
{
        return _b;
}

float DecoratedImage::a()
{
        return _a;
}

BlendStyle DecoratedImage::blendStyle()
{
        return _blendStyle;
}

void DecoratedImage::setNrFrames(int nrFrames)
{
        this->_nrFrames = nrFrames;
        _curFrame = 0;
}

void DecoratedImage::setHandler(NextFrameHandler handler)
{
        this->handler = handler;
}

void DecoratedImage::setFrame(int frame, bool update)
{
        int old_tick = _curFrame;
        if (frame >= 0 && frame < _nrFrames)
                _curFrame = frame;
        if (update)
                handler(this, old_tick, _curFrame);
}

void DecoratedImage::setReverse(bool reverse)
{
        this->reverse = reverse;
}

int DecoratedImage::nrFrames()
{
        return _nrFrames;
}

int DecoratedImage::curFrame()
{
        return _curFrame;
}

bool DecoratedImage::reversed()
{
        return reverse;
}

void DecoratedImage::nextFrame()
{
        int old_tick = _curFrame;
        if (_nrFrames > 1 && handler) {
                if (!reverse && _curFrame < _nrFrames)
                        _curFrame ++;
                else if (reverse && _curFrame > 0)
                        _curFrame --;
                handler(this, old_tick, _curFrame);
        }
}
